import { AngleI } from "./type";

/** 角度计算类 */
export default class Angle implements AngleI {
	/** 一度的值 */
	public static OneAngle: number = Math.PI / 180;

	/** 度数代表的值 */
	private value!: number;

	/** 度数 */
	private angle!: number;

	/** 度数代表的值 */
	public get Value(): number {
		return this.value;
	}
	public set Value(value: number) {
		this.value = value;
		this.angle = value / Angle.OneAngle;
	}

	/** 度数 */
	public get Angle(): number {
		return this.angle;
	}

	public set Angle(angle: number) {
		angle = angle;
		this.angle = angle;
		this.value = angle * Angle.OneAngle;
	}

	/** 四舍五入角度 */
	public static FixedAngle(angle: number) {
		angle = angle % 360;
		if (angle < 0) {
			angle = 360 + angle;
		}
		return angle;
	}

	/**
	 * 构造函数
	 * @param angle 度数
	 */
	public constructor(angle: number) {
		this.Angle = angle;
	}

	/**
	 * 位于范围内
	 * @param start 开始角度
	 * @param end 结束角度
	 * @param param2 是否包含边界
	 */
	public OnRange(start: Angle, end: Angle, { inStart, inEnd }: { inStart?: boolean, inEnd?: boolean } = {}): boolean {
		const onAngle = Angle.FixedAngle(this.Angle);
		const startAngle = Angle.FixedAngle(start.Angle);
		const endAngle = Angle.FixedAngle(end.Angle);
		if (startAngle > endAngle) {
			return (inStart ? onAngle >= startAngle : onAngle > startAngle)
				|| (inEnd ? onAngle <= endAngle : onAngle < endAngle);
		} else {
			return (inStart ? onAngle >= startAngle : onAngle > startAngle)
				&& (inEnd ? onAngle <= endAngle : onAngle < endAngle);
		}
	}

	/**
	 * 位于范围内
	 * @param start 开始角度
	 * @param end 结束角度
	 * @param param2 是否包含边界
	 */
	public OnRangeMiddle(angle: number, size: number, { inStart, inEnd }: { inStart?: boolean, inEnd?: boolean } = {}): boolean {
		const onAngle = Angle.FixedAngle(this.Angle);
		const startAngle = Angle.FixedAngle(angle - size);
		const endAngle = Angle.FixedAngle(angle + size);
		if (startAngle > endAngle) {
			return (inStart ? onAngle >= startAngle : onAngle > startAngle)
				|| (inEnd ? onAngle <= endAngle : onAngle < endAngle);
		} else {
			return (inStart ? onAngle >= startAngle : onAngle > startAngle)
				&& (inEnd ? onAngle <= endAngle : onAngle < endAngle);
		}
	}

	/**
	 * 旋转
	 * @param angle 旋转角度
	 */
	public Rotate(angle: Angle) {
		angle.Angle += this.Angle;
		return new Angle(angle.Angle);
	}

	/**
	 * 旋转
	 * @param angle 旋转角度
	 */
	public RotateAngle(angle: number) {
		angle += this.Angle;
		return new Angle(angle);
	}
}
